package com.uflower.product.service.impl;

import cn.hutool.db.sql.Order;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.uflower.common.exception.WareReduceExcption;
import com.uflower.common.to.WareSkuReduceTo;
import com.uflower.common.to.mq.OrderEntityTo;
import com.uflower.common.to.mq.StockLockedTo;
import com.uflower.common.utils.R;
import com.uflower.product.feign.OrderFeignService;
import com.uflower.product.feign.UserFeignService;
import com.uflower.product.to.FareTo;
import com.uflower.product.to.SkuHasStockTo;
import com.uflower.product.vo.MemberAddressVo;
import com.uflower.product.vo.OrderVo;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.uflower.common.utils.PageUtils;
import com.uflower.common.utils.Query;

import com.uflower.product.dao.SkuInfoDao;
import com.uflower.product.entity.SkuInfoEntity;
import com.uflower.product.service.SkuInfoService;
import org.springframework.transaction.annotation.Transactional;


@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {
    @Autowired
    UserFeignService userFeignService;


    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    OrderFeignService orderFeignService;

    @Override
    public List<SkuInfoEntity> listBySpuId(Long spuId) {
        List<SkuInfoEntity> skus = list(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
        return skus;
    }

    @Override
    public void unlockStock(StockLockedTo to) {
//        skuInfoService.unlockStock(to);
        String orderSn = to.getOrderSn();
        if(orderSn != null){
            R r = orderFeignService.getOrderStatus(orderSn);
            if(r.getCode()  == 0){
                OrderVo order = r.getData(new TypeReference<OrderVo>() {
                }, "order");
                if(order == null||order.getStatus() == 4){
                    //订单已经被取消了
                    to.getItems().forEach(item->{
                        unLockStock(item.getSkuId(), item.getLockedNum());
                    });
                }
            }

        }
    }


    //订单回滚，不存在，必须解锁库存
    //订单存在，已取消，必须解锁
                //没取消，不能解锁

    @Override
    public FareTo getFare(Long addrId) {
        FareTo fareTo = new FareTo();
        R addrInfo = userFeignService.info(addrId);
        MemberAddressVo receiveAddress = addrInfo.getData(new TypeReference<MemberAddressVo>() {
        }, "receiveAddress");
        if(receiveAddress != null){
            String phone = receiveAddress.getPhone();
            // 获取最后一位
            String fare = phone.substring(phone.length() - 1);
            BigDecimal bigDecimal = new BigDecimal(fare);

            fareTo.setFare(bigDecimal);
            fareTo.setAddressVo(receiveAddress);
        }
        return fareTo;
    }

    /**
     * 解锁库存场景
     * 1、下单成功，订单过期被系统自动取消，被用户手动取消
     * 2、下单成功，锁库存也成功，但其它业务调用失败导致订单回滚，库存也须回滚
     * @param reduceTo
     * @throws WareReduceExcption
     */
    @Override
    @Transactional
    public void orderReduceStock(WareSkuReduceTo reduceTo) throws WareReduceExcption{
        StockLockedTo stockLockedTo = new StockLockedTo();
        List<StockLockedTo.StockLockItem> items = new ArrayList<>();
        reduceTo.getOrderItemVos().stream().forEach(item->{
            Long skuId = item.getSkuId();
            SkuInfoEntity skuInfo = this.getById(skuId);
            if(skuInfo.getWareCount() >= item.getCount()){
                skuInfo.setWareCount(skuInfo.getWareCount()-item.getCount());
                this.baseMapper.update(skuInfo,new UpdateWrapper<SkuInfoEntity>().eq("sku_id",skuId));

                StockLockedTo.StockLockItem lockItem = new StockLockedTo.StockLockItem(item.getSkuId(),item.getCount());
                items.add(lockItem);
            }else{
                throw new WareReduceExcption("库存不足",500);
            }
        });
        stockLockedTo.setOrderSn(reduceTo.getOrderSn());
        stockLockedTo.setItems(items);
        rabbitTemplate.convertAndSend("stock-event-exchange","stock.delay",stockLockedTo);
    }
    private void unLockStock(Long skuId,Integer num){
        this.baseMapper.unlockStock(skuId,num);
    }
    @Override
    public List<SkuHasStockTo> getSkusHasStock(List<Long> skuIds) {
        List<SkuInfoEntity> skusStock= this.baseMapper.getSkusStock(skuIds);
        List<SkuHasStockTo> skusHasStock = skusStock.stream().map(item -> {
            SkuHasStockTo skuHasStockTo = new SkuHasStockTo();
            skuHasStockTo.setSkuId(item.getSkuId());
            skuHasStockTo.setHasStock(item.getWareCount() > 0 ? true : false);
            return skuHasStockTo;
        }).collect(Collectors.toList());
        return skusHasStock;
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                new QueryWrapper<SkuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void saveSkuInfo(SkuInfoEntity skuInfoEntity) {
        this.baseMapper.insert(skuInfoEntity);
    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SkuInfoEntity> wrapper = new QueryWrapper<>();

        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            wrapper.and((w)->{
                w.eq("sku_id",key).or().like("sku_name",key);
            });
        }
        String brandId = (String) params.get("brandId");
        if(!StringUtils.isEmpty(key) &&! "0".equalsIgnoreCase(brandId)){
            wrapper.eq("brand_id",brandId);
        }

        String catelogId = (String) params.get("catelogId");
        if(!StringUtils.isEmpty(key) &&! "0".equalsIgnoreCase(catelogId)){
            wrapper.eq("catalog_id",catelogId);
        }

        String min = (String) params.get("min");
        if(!StringUtils.isEmpty(key)){
            wrapper.ge("price",min);
        }

        String max = (String) params.get("max");


        if(!StringUtils.isEmpty(key)){
            try{
                BigDecimal bigDecimal = new BigDecimal(max);
                if(bigDecimal.compareTo(new BigDecimal(0))==1){
                    wrapper.le("price",max);
                }
            } catch (Exception e){

            }
        }

        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }


    public BigDecimal getPriceBySkuId(Long skuId) {
        return this.baseMapper.getPriceBySkuId(skuId);
    }


}